<template>
  <a-modal
    wrapClassName="select-modal"
    :title="title"
    :visible="visible"
    v-bind="commonDlgProps"
    :confirmLoading="confirmLoading"
    :width="900"
    @ok="handleOk"
    @cancel="handleCancel"
  >
    <a-row :gutter="15">
      <a-col :span="modalLayout[0]">
        <div class="col-title">{{ subTitle }}</div>
        <div class="col-content">
          <a-tree
            class="tree--custom"
            defaultExpandAll
            :showIcon="false"
            :checkable="treeCheckable"
            :checkStrictly="treeCheckStrictly"
            :treeData="treeData"
            :selectedKeys="selectedKeys"
            :checkedKeys="checkedTreeKeys"
            @check="onCheckTreeNode"
            @select="onSelectTreeNode"
          >
            <template slot="title" slot-scope="scopeProps">
              <div class="tree--custom-node" :value="scopeProps.key">
                <div class="tree--custom-node-text" :title="scopeProps.name">
                  <!--<ellipsis length="100%" tooltip>-->
                  <!--{{scopeProps.name}}-->
                  <!--</ellipsis>-->
                  {{ scopeProps.name }}
                </div>
              </div>
            </template>
          </a-tree>
        </div>
      </a-col>
      <a-col :span="modalLayout[1]" v-if="showList">
        <div class="col-title">
          <span>可选项</span>
          <a-alert :message="`最多选择${checkboxMax}项`" type="info" show-icon v-if="checkboxMax !== 99999999" />
        </div>
        <div class="col-content">
          <div class="col-check-area">
            <a-input v-model="searchValue" @change="onChangeSearch" allowClear placeholder="输入关键字搜索" />
            <div class="check-list" style="margin-top: 10px">
              <template v-if="list.length > 0">
                <a-checkbox-group
                  ref="checkboxGroup"
                  v-if="multiple"
                  :options="list"
                  :value="checkedList"
                  @change.native="onCheckChangeNative"
                >
                  <!--<template slot="label" slot-scope="option" >-->
                  <!--<div class="qqq" :title="option.label">-->
                  <!--{{option.label}}-->
                  <!--</div>-->
                  <!--</template>-->
                </a-checkbox-group>
                <a-radio-group v-else v-model="radioCheck" @change="onRadioChange">
                  <a-radio class="radioStyle" v-for="i in list" :key="i.id" :value="i.id">
                    {{ i.name }}
                  </a-radio>
                </a-radio-group>
              </template>
              <a-empty style="margin-top: 40px" v-else />
              <!--{{list}}-->
              <!--{{checkedList}}-->
            </div>
          </div>
        </div>
      </a-col>
      <a-col :span="modalLayout[2]">
        <div class="col-title">已选项</div>
        <div class="col-content">
          <div class="col-check-area" v-if="showList">
            <div class="col-sub-title">
              已选条目<span>{{ checkedList.length }}</span>
            </div>
            <div class="check-list" v-if="checkedList.length > 0 || radioCheck">
              <div class="check-list-item" v-for="(x, i) in totalCheckedList" :key="i">
                <div class="check-list-item-inner" :class="{ 'has-input-number': inputNumber }" :value="x.value">
                  <span class="check-list-item-inner_text" :title="x.label">{{ x.label }}</span>
                  <a-input-number
                    v-if="inputNumber"
                    size="small"
                    :min="1"
                    :max="inputNumberMax"
                    :precision="0"
                    v-model="x.number"
                    placeholder="输入数量"
                  />
                  <div class="remove-item" title="删除" @click="onRemove(x, i)">
                    <a-icon type="close-circle" />
                  </div>
                </div>
                <!--<a-icon type="close-circle" @click="onRemove(x,i)"/>-->
              </div>
            </div>
            <a-empty v-else />
            <!--{{totalCheckedList}}-->
          </div>
          <div class="col-check-area" v-if="treeCheckable">
            <div class="col-sub-title">
              已选树节点<span>{{ checkedTreeNodes.length }}</span>
            </div>
            <div class="check-list" v-if="checkedTreeNodes.length > 0">
              <div class="check-list-item" v-for="(x, i) in checkedTreeNodes" :key="i">
                <div class="check-list-item-inner" :class="{ 'has-input-number': treeInputNumber }" :key="x.key">
                  <span class="check-list-item-inner_text" :title="x.title">{{ x.title }}</span>
                  <a-input-number
                    v-if="treeInputNumber"
                    size="small"
                    :min="1"
                    :max="treeInputNumberMax"
                    :precision="0"
                    v-model="x.number"
                    placeholder="输入数量"
                  />
                  <div class="remove-item" title="删除" @click="onRemoveTreeNode(x)">
                    <a-icon type="close-circle" />
                  </div>
                </div>
                <!--<a-icon type="close-circle" @click="onRemove(x,i)"/>-->
              </div>
            </div>
            <a-empty v-else />
            <!--{{checkedTreeNodes}}-->
          </div>
        </div>
      </a-col>
    </a-row>
  </a-modal>
</template>

<script>
// import {tableSearchFormMixin} from '../../../utils/mixin'
import debounce from 'lodash/debounce'
import { breadFirstTree } from '../../utils/util'

export default {
  name: 'SelectModal',
  mixins: [],
  data () {
    return {
      visible: false,
      commonDlgProps: {
        maskClosable: false,
        keyboard: false
      },
      defaultSelTreeKeys: [],
      selectedKeys: [],
      selectedNode: null,

      checkedTreeKeys: [], // 选中的树key
      checkedTreeNodes: [], // 选中的树节点数据
      allList: [], // 根据树节点获取的所有列表数据
      list: [], /// 搜索出来的列表数据
      checkedList: [], // 选中的列表value
      totalCheckedList: [], // 选中的列表数据
      originDisabledList: [], // 打开选择器时失效的列表数据

      searchValue: '', // 搜索关键字
      radioCheck: '', // 单选选中的数据
      confirmLoading: false
    }
  },
  props: {
    treeData: {
      type: Array,
      default () {
        return []
      }
    },
    defaultSelectedTreeKeys: {
      type: Array,
      default () {
        return []
      }
    },
    selectTreeNode: {
      type: Function,
      default () {
        return (node, resolve) => {
          resolve([])
        }
      }
    },
    treeCheckable: {
      type: Boolean,
      default: false
    },
    treeCheckStrictly: {
      type: Boolean,
      default: true
    },
    treeInputNumber: {
      type: Boolean,
      default: false
    },
    treeInputNumberMax: {
      type: Number,
      default: 99999999
    },
    inputNumber: {
      type: Boolean,
      default: false
    },
    inputNumberMax: {
      type: Number,
      default: 99999999
    },
    showList: {
      type: Boolean,
      default: true
    },
    checkboxMax: {
      type: Number,
      default: 99999999
    },
    title: {
      type: String,
      default: '选择'
    },
    subTitle: {
      type: String,
      default: '树数据'
    },
    multiple: {
      type: Boolean,
      default: true
    }
  },
  computed: {
    modalLayout () {
      if (this.showList) {
        return [10, 7, 7]
      }
      return [14, 0, 10]
    }
    // /**
    //  * 初始的禁用的列表项，缓存起来
    //  */
    // originDisabledList(){
    //   return
    // }
  },
  watch: {
    // 'visible'(nv){
    //   if(nv){
    //     breadFirstTree(this.treeData, (node) => {
    //       if(node.key===this.defaultSelectedTreeKeys[0]){
    //         this.onSelectTreeNode(this.defaultSelectedTreeKeys, node);
    //         return false;
    //       }
    //       return true;
    //     }, 'children');
    //   }
    // },
    // 外部选中的节点发生变化触发
    defaultSelectedTreeKeys (nv) {
      // this.selectedKeys=[...nv];
      console.log('bbbbbb')
      if (JSON.stringify(nv) !== JSON.stringify(this.defaultSelTreeKeys)) {
        breadFirstTree(
          this.treeData,
          node => {
            if (node.key === nv[0]) {
              this.onSelectTreeNode([node.key], node)
              return false
            }
            return true
          },
          'children'
        )
        this.defaultSelTreeKeys = nv
      }
    },
    checkedList (nv, ov) {
      // 勾选checkbox
      if (nv.length > ov.length) {
        // 如果勾选项已经达到最大限制，则禁用除了最新勾选的其他所有的checkbox（包括已选中）
        if (nv.length === this.checkboxMax) {
          const newValue = nv[nv.length - 1]
          this.list.forEach(item => {
            item.disabled = item.value !== newValue
          })
        }
        // 根据已选中的value得到list对应的完成列表
        const transferList = this.list.filter(item => nv.indexOf(item.value) > -1)
        this.totalCheckedList = this.totalCheckedList.concat(
          transferList.filter(item_ => {
            let isRepeat = false
            this.totalCheckedList.forEach(item => {
              if (item.value === item_.value) {
                isRepeat = true
                return true
              }
            })
            return !isRepeat
          })
        )
      } else {
        // 取消勾选checkbox
        // 如果勾选项小于最大限制，则打开初始disabled为false的checkbox
        if (nv.length < this.checkboxMax) {
          this.list.forEach(item => {
            const data = this.originDisabledList.find(obj => obj.value === item.value)
            // 如果该数据初始disabled为false，要复原disabled
            if (!data) {
              item.disabled = false
            }
          })
        }
        this.totalCheckedList = this.totalCheckedList.filter(item => nv.indexOf(item.value) > -1)
      }
    },
    radioCheck (nv, ov) {
      this.totalCheckedList = this.list.filter(item => nv === item.value)
    }
  },
  created () {},
  methods: {
    open () {
      this.visible = true
    },
    close () {
      this.visible = false
    },
    onSelectTreeNode (keys, data) {
      if (keys.length === 0) return
      this.selectedNode = data.node ? data.node.dataRef : data
      if (this.selectedKeys[0] !== keys[0]) {
        this.selectedKeys = keys
      }
      const p = new Promise(resolve => {
        if (this.selectTreeNode) {
          this.selectTreeNode(this.selectedNode, resolve)
        } else {
          resolve([])
        }
      })
      p.then(listData => {
        this.list = listData
        this.allList = listData
        this.searchValue = ''
        this.originDisabledList = JSON.parse(JSON.stringify(this.allList.filter(item => item.disabled)))
      })
    },
    onCheckTreeNode (checkedKeys, data) {
      this.checkedTreeNodes = data.checkedNodes.map(node => node.data.props.dataRef)
      if (this.treeCheckStrictly) {
        this.checkedTreeKeys = checkedKeys.checked
        const currentChecked = data.checked
        const currentNodeData = data.node.$props.dataRef
        breadFirstTree(
          currentNodeData.children,
          node => {
            node.disableCheckbox = currentChecked
            return true
          },
          'children'
        )
        // 如果选中了一个父节点，筛选去除掉其所有的子节点
        if (currentChecked) {
          breadFirstTree(
            currentNodeData.children,
            node => {
              this.checkedTreeNodes = this.checkedTreeNodes.filter(checkNode => checkNode.key !== node.key)
              this.checkedTreeKeys = this.checkedTreeKeys.filter(checkKey => checkKey !== node.key)
              return true
            },
            'children'
          )
        }
      } else {
        this.checkedTreeKeys = checkedKeys
      }
    },
    onChangeSearch: debounce(function (e) {
      let val = e.target.value
      if (val) {
        val = val.toUpperCase()
        this.list = this.allList.filter(item => {
          if (undefined !== item.searchKey && item.searchKey !== null) {
            return item.searchKey.indexOf(val) > -1
          }
          return item.label.indexOf(val) > -1
        })
      } else {
        this.list = [...this.allList]
      }
    }, 200),
    handleOk () {
      const newList = []
      for (const item of this.totalCheckedList) {
        if (this.inputNumber && (item.number === undefined || item.number === null)) {
          this.$message.error('请输入已选项数量')
          return false
        }
        newList.push({
          ...item,
          label: item.label,
          value: item.value,
          number: item.number,
          type: 'list'
        })
      }
      for (const item of this.checkedTreeNodes) {
        if (this.treeInputNumber && item.number === undefined) {
          this.$message.error('请输入已选项数量')
          return false
        }
        newList.push({
          ...item,
          label: item.title,
          value: item.key,
          number: item.number,
          type: 'tree'
        })
      }
      this.$emit('sure', newList)
      this.clear()
    },
    handleCancel () {
      this.clear()
      this.close()
    },
    clear () {
      this.selectedKeys = []
      this.checkedTreeKeys = []
      this.checkedTreeNodes = []
      this.totalCheckedList = []
      this.checkedList = []
      this.radioCheck = ''
      this.list = []
    },
    onCheckChangeNative (e) {
      const checkbox = e.target
      const value = checkbox._value
      if (!checkbox.checked) {
        this.checkedList = Array.from(new Set([...this.checkedList, value]))
      } else {
        this.checkedList = this.checkedList.filter(item => item !== value)
      }
    },

    onRadioChange (e) {
      console.log('radio checked', e.target.value)
    },
    onRemove (item, index) {
      this.totalCheckedList.splice(index, 1)
      this.checkedList = this.checkedList.filter(checkedValue => item.value !== checkedValue)
      this.radioCheck = ''
    },
    // 暂时的写法，通过触发事件来删除选中树形节点，虽然奇葩，但是省了好多行代码和脑细胞；
    // 所以我觉得这种写法很好用，就这么写吧
    onRemoveTreeNode (item) {
      window.document.querySelector(`[value='${item.key}']`).parentElement.parentElement.previousElementSibling.click()
    },
    setSureLoading (v) {
      this.confirmLoading = v
    }
  }
}
</script>

<style lang="less">
.select-modal {
  .ant-modal {
    height: 98%;
    /*min-height: 400px;*/
    max-height: 900px;
    top: 2%;
  }

  .ant-modal-content {
    height: 100%;
  }

  .ant-modal-body {
    padding: 12px 25px 0;
    height: calc(100% - 56px - 53px);
    overflow: hidden;

    .ant-row,
    .ant-col {
      height: 100%;
    }
  }

  .col-title {
    border-bottom: 1px solid #eee;
    padding-bottom: 8px;
    font-weight: bold;
    display: flex;
    justify-content: space-between;
    height: 35px;
    line-height: 24px;

    .ant-alert-info {
      padding: 1px 10px 1px;
      font-size: 13px;
      font-weight: normal;
    }

    .ant-alert-info .ant-alert-icon {
      position: static;
      margin-right: 5px;
    }
  }

  .col-content {
    height: calc(100% - 35px);
    overflow-y: auto;
    overflow-x: hidden;
    position: relative;

    &::-webkit-scrollbar {
      width: 0.5em;
      background-color: #ececec;
    }

    &::-webkit-scrollbar-track {
      background-color: rgba(255, 255, 255, 0.5);
      border-radius: 3em;
    }

    &::-webkit-scrollbar-thumb {
      background-color: rgba(146, 141, 157, 0.41);
      border-radius: 3em;
    }
  }

  .col-check-area {
    padding: 10px 0;

    & + .col-check-area {
      border-top: 1px solid #eee;
    }

    .ant-empty-image {
      height: 55px;
    }

    .ant-empty-description {
      font-size: 13px;
    }
  }

  .check-list {
    display: block;

    .ant-checkbox-group {
      width: 100%;
    }
    .radioStyle {
      display: block;
      height: 30px;
      line-height: 30px;
    }
    .ant-checkbox-wrapper {
      display: flex;
      align-items: center;
      margin-bottom: 6px;

      .ant-checkbox {
        display: block;
        top: 0;
      }

      .ant-checkbox + span {
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
        display: block;
      }
    }
  }

  .check-list-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 9.5px;
  }

  .check-list-item-inner {
    width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    /*&.has-input-number{*/
    /*.check-list-item-inner_text{*/
    /*width: calc(100% - 75px);*/
    /*}*/
    /*}*/

    .check-list-item-inner_text {
      display: block;
      /*width: calc(100%);*/
      flex: 1;
      text-overflow: ellipsis;
      overflow: hidden;
      white-space: nowrap;
    }

    .ant-input-number {
      width: 90px;
    }
  }

  .remove-item {
    width: 20px;
    text-align: right;
    line-height: 24px;

    i {
      cursor: pointer;
      color: #1890ff;
    }
  }

  .ant-empty {
    margin-top: 20px;
  }

  .col-sub-title {
    font-size: 12px;
    font-weight: bold;

    span {
      margin-left: 10px;
      /*font-weight: normal;*/
    }
  }
}
</style>
